package net.wanho.shop.advice;

import cn.hutool.json.JSONUtil;
import net.wanho.shop.mapper.RoleMapper;
import net.wanho.shop.mapper.UserMapper;
import net.wanho.shop.po.OperLog;
import net.wanho.shop.service.OperLogService;
import net.wanho.shop.util.AddressUtil;
import net.wanho.shop.util.CurrentUtil;
import net.wanho.shop.util.ServletUtil;
import net.wanho.shop.vo.AjaxResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 操作日志切面
 */
@Component
@Aspect
public class OperLogAspect {

    @Resource
    private OperLogService operLogService;
    @Resource
    private UserMapper userMapper;
    @Resource
    private RoleMapper roleMapper;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PutMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void pc() {
    }

    @Around("pc()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 放行特定请求
        List<String> list = Arrays.asList("login", "captchaLogin", "logout", "notify", "smsLogin");
        if (list.contains(joinPoint.getSignature().getName())) {
            try {
                return joinPoint.proceed();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }


        HttpServletRequest request = ServletUtil.getRequest();
        int businessType = 0;
        switch (request.getMethod()) {
            case "POST":
                businessType = 1;
                break;
            case "PUT":
                businessType = 2;
                break;
            case "DELETE":
                businessType = 3;
                break;
        }

        OperLog operLog = new OperLog();
        operLog.setTitle(request.getRequestURI().split("/")[4]);
        operLog.setBusinessType(businessType);
        operLog.setMethod(joinPoint.getSignature().getName());
        operLog.setRequestMethod(request.getMethod());
        operLog.setOperatorType(1);
        operLog.setOperName(userMapper.selectById(CurrentUtil.getId()).getUsername()); // 通过token获取用户名
        operLog.setRoleName(roleMapper.selectByUserId(CurrentUtil.getId()).getRoleName()); // 通过token获取用户id，然后获取用户的角色
        operLog.setOperUrl(request.getRequestURL().toString());
        operLog.setOperIp(AddressUtil.getIpAddr(request));
        operLog.setOperLocation(AddressUtil.getLocationByIp(operLog.getOperIp()));
        operLog.setOperParam(Arrays.toString(joinPoint.getArgs()));
        operLog.setOperTime(LocalDateTime.now());

        Long start = System.currentTimeMillis();
        try {
            // 核心业务
            Object res = joinPoint.proceed();
            operLog.setJsonResult(JSONUtil.toJsonStr(res));
            operLog.setStatus(0);

            return res;
        } catch (Throwable e) {
            operLog.setJsonResult(JSONUtil.toJsonStr(AjaxResult.error(e.getMessage())));
            operLog.setStatus(1);
            operLog.setErrorMsg(e.getMessage());
            throw new RuntimeException(e.getMessage());
        } finally {
            Long end = System.currentTimeMillis();
            operLog.setCostTime(end - start);

            // 记录操作日志
            operLogService.add(operLog);
        }
    }

}